在原生的 JavaScript 裡,我們會操作 DOM 來修改網頁程式碼,但這麼做會很容易不小心改到不需要變動的地方,React 解決了這件事,讓 React 程式碼在更新 DOM 之前,先用 JavaScript 製造出虛擬的 DOM - Virtual DOM,利用這個 Virtual DOM 模擬所有更新後應該要長的樣子,設計一個特殊的 Diff 演算法去比較當前的 DOM 和 模擬出的虛擬 DOM 的差別,最後 React 只會去修改有不一樣的地方,避免資源的浪費。
首先來看看下面這三行程式碼:
第一行為導入 React
第二行為導入 ReactDOM
第三行為開發 React 程式的進入點,讓所有 React 程式碼透過 ReactDOM 提供的 render 函式綁定到 HTML 裡,render 的第一個參數是要渲染到畫面上的元素,第二個參數決定元素要放到哪個 HTML 元素內。
// 獲得 React & ReactDom module
import React from "react";
import ReactDOM from "react-dom";
// 渲染到畫面上
ReactDom.render(<div>Hello, World></div>, document.querySelector("#root"));
第三行將 <div>Hello, World></div>
綁定到 <div id="root"></div>
,而這個 html 檔案會在 public 資料夾裡面的 index.html,打開會發現 body 裡面有個 id 為 root 的 div 元素,這就是我們綁定 React 程式的地方,所有專案的元素都會被 React 包進 index.html 的 <div id="root"></div>
裡面。
下面只是為了理解 React 背後的原理,所以使用 React.createElement,但平常不會使用這些做法,而會使用 JSX
React.createElement("HTML tag", css設定, "HTML tag 的內容")
// 獲得 React & ReactDom module
import React from "react";
import ReactDOM from "react-dom";
// 製作 h1
function App() {
return React.createElement("h1", null, "This is React App.");
}
// ReactDOM.render(渲染的內容,要渲染的位置)
ReactDom.render(React.createElement(App), document.querySelector("#root"));
由此可知 React 的原理為,用 function 製造出 Element,再選定 HTML 文件的某個地方讓創造出來的 Element 顯示到那裡。
因為一個 function 不能 return 好幾個值,所以要製作多個 html 標籤的話,在 React.createElement() 裡面的第 3 個參數要是一個 Array。
// 獲得 React & ReactDom module
import React from "react";
import ReactDOM from "react-dom";
// 製作 div,裡面放 h1,p,button
function App() {
return React.createElement("div", null, [
React.createElement("h1", { style: { color: "red" } }, "My Profile."),
React.createElement("p", null, "My Name is Helen."),
React.createElement("button", null, "Check my profile."),
]);
}
// ReactDOM.render(渲染的內容,要渲染的位置)
ReactDom.render(React.createElement(App), document.querySelector("#root"));
上面的例子使用了複雜的 JavaScript 建構出 React component,為了使開發更有效率,我們會需要 JSX。
假如我們寫這樣的 code:const h1 = <h1>Hello world</h1>
,這樣運作時根本不會起作用,因為在 JavaScript 裡不能包含 HTML,所以當這樣寫的時候瀏覽器看不懂,而 JSX 就是讓我們在寫 React 時,可以把 JavaScript 寫得很像 HTML,讓我們在 JavaScript 裡可以使用標籤式的語法來寫 React,且內建 Babel 功能,會自動將 JSX 編譯成瀏覽器能理解的 JavaScript(JSX 會被編譯成前面提到的 React.createElement 的作法)。
將上面 React.createElement 的程式碼改為 JSX :
// 獲得 React & ReactDom module
import { div } from "prelude-ls";
import React from "react";
import ReactDOM from "react-dom";
// JSX
function App() {
return (
<div>
<h1 style={{ color: "red" }}>My Profile.</h1>
<p>My Name is Helen.</p>
<button>Check my profile.</button>
</div>
);
}
// ReactDOM.render(渲染的內容,要渲染的位置)
ReactDom.render(<App />, document.querySelector("#root"));
import { div } from "prelude-ls";
import React from "react";
import ReactDOM from "react-dom";
function App() {
return (
<React.Fragment>
<h1 style={{ color: "red" }}>My Profile.</h1>
<p>My Name is Helen.</p>
<button>Check my profile.</button>
</React.Fragment>
);
}
ReactDom.render(<App />, document.querySelector("#root"));
也可以使用 React.Fragment 的簡寫語法:
import { div } from "prelude-ls";
import React from "react";
import ReactDOM from "react-dom";
function App() {
return (
<>
<h1 style={{ color: "red" }}>My Profile.</h1>
<p>My Name is Helen.</p>
<button>Check my profile.</button>
</>
);
}
ReactDom.render(<App />, document.querySelector("#root"));
使用 React.Fragment 後,如果去檢視 DOM,會發現並沒有渲染成任何標籤
<div id="root">
略
<div/>
在 tag 裡加入 style={{ }}
,第一個括號表示傳參數,第二個表示參數裡的 CSS 設定
例如:<h1 style={{ color: "red" }}>My Profile.</h1>
{ }
包覆
例如:<h1>{ title.toUpperCase() }</h1>
因為大括號裡代表寫入的 JavaScript,h1 的內容會變成 TITLE
因為在 JavaScript 中已經有 class 和 for,當我們在寫 JSX 時,會以 className 來表示 HTML 的 class 屬性,而以 htmlFor 表示 for。
例如:<h1 className="title">Hello World</h1>
參考資料:
一本在誠品看到的書,忘記書名是什麼了 XD